#ifndef TETRAHEDRON_STATE_H
#define TETRAHEDRON_STATE_H

#include "Matrix.h"

class TetrahedronState;
class Tetrahedron;

typedef Real (*TetrahedronEnergy)(Real, Real, Real);
typedef int  (*TetrahedronForceFunction)(TetrahedronState const *, Matrix3*, Matrix3 const &);
typedef int  (*TetrahedronPrecomputeDisplacement)(TetrahedronState*, Matrix3 const&);
typedef int  (*TetrahedronIncrementalDForce)(TetrahedronState const*, Matrix3*, Matrix3 const &);
typedef int  (*TetrahedronDForceFunction)(TetrahedronState const*, Matrix3*, Matrix3*, Matrix3 const&, Matrix3 const&);

class TetrahedronState
{
public:
	int incident_nodes_[4];
	/*
	Entry i,j -> force on i-th entry of node number j.

	Node no. 3 (4th node) is

	*/
	Matrix3 inverse_location_;
	Matrix3 invloc_transpose_;

	Real volume_;

	/*  bool incident_valid_ ;
	bool geometry_valid_;*/

	bool degenerate_b_;

	TetrahedronState ();

	void Precompute (Tetrahedron*); 

#if 0
	/*
	Can be used for various purposes.
	*/
	Matrix3 precompute_mat_[5];
	Real precompute_real_[4];
#endif

	void VectorToMatrix3 (Matrix3 * dest_mat, Real const*src_vec) const; 
	void Matrix3ToVector (Real * dest_vec, Matrix3 const &src_mat) const;

	Real LinearElasticEnergy (Real const *) const;  
	Real ElasticEnergy (TetrahedronEnergy, Real const *) const;
	int ElasticForce (TetrahedronForceFunction, Real*,Real const*) const;
	int ElasticForceDerivative (TetrahedronDForceFunction, Real*,Real*, Real const*,Real const*) const;
	int PrecomputeForDisplacement (TetrahedronPrecomputeDisplacement, Real const*) ;
	int IncrementalDForce (TetrahedronIncrementalDForce, Real*,Real const*)const;  
};

#endif